package ngat.oss;

import ngat.phase2.*;
import ngat.astrometry.*;
import ngat.phase2.*;

import java.io.*;
import java.util.*;
import java.text.*;
import java.awt.*;

import jyd.dbms.*;
import jyd.storable.*;
import jyd.collection.*;

/**
 * Populates a Phase II database with randomly chosen values for test purposes.
 *
 * $Id: MakeDB.java,v 1.1 2006/11/27 08:45:00 snf Exp $
 *
 */
public class MakeDB {   

    public static final int BRIGHT = 0;
    
    public static final int DARK   = 1;
    
    public static final int EXCELLENT = 0;
    
    public static final int AVERAGE   = 1;
    
    public static final int POOR      = 2;

    public static final long REGCODE = 0xAAAABA5EC0DEBBBBL;

    public static final int RAT    = 0x0001;
    public static final int SUPIR  = 0x0002;
    public static final int MES    = 0x0004;
    public static final int NUVIEW = 0x0008;

    static final String[] lowers = new String[] {"clear","SDSS-R","SDSS-Z","clear","SDSS-I","clear","clear"};
    static final String[] uppers = new String[] {"SDSS-G","clear","SDSS-U","Bessell-B","clear","Bessell-V","clear"};
    
    //static final String[] lowers = new String[] {"clear","clear","clear","clear","clear","clear","clear",    };
    //static final String[] uppers = new String[] {"clear", "clear","clear","clear","Bessell-B", "Bessell-V", "neutral2"};
   
    public static void main(String args[]) {
	
	SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
	SimpleDateFormat mdf = new SimpleDateFormat("MMM-dd:HH:mm");

	Date start = new Date();
 
	//  GraphPlot plot = new GraphPlot(25000, 0.0f, 360.0f, -90.0f, 90.0f);	
//  	GraphFrame graph = new GraphFrame("Sky Positions", plot);
//  	plot.annotate("Sky Positions (RA/Dec)", 90.0f, 100.0f);
//    	plot.setMark(0, GraphPlot.SPOT);
//    	plot.setMarkSize(0, 2);
//    	plot.setMarkColor(0, Color.blue);	
//    	plot.setXTitle("RA (degs).");
//    	plot.setYTitle("Dec (degs).");
//    	//plot.setJoinPoints(0, true);
//  	graph.setBounds(0,0,600,600);
//  	graph.setVisible(true);

	if (args.length < 2) {
	    usage();
	    return;
	}

	try {
	    start = sdf.parse(args[0]);
	} catch (ParseException pe) {
	    System.err.println("Error - start date not defined using today:");
	}
	
	int total = 0;
	int fixed = 0;
	int nn = 0;
	long yearStart = start.getTime();
	long msecYear = 31536000000L; // millisecs/year!!
	

	int countObs = 0;
	int countGroup = 0;

	final String[] tags = {"JMU", "PPARC", "IAC", "CCI", "NSO", "AMAT", "LT-COM", "SHARED"};

	final String[] users = {"snfraser", "javaman", "welshie", "cjmott", "iasteel", "jmmarch", "rjsmith", "andreja", "lisamorales", "geronimo"};

	int pcc = 0;

	NumberFormat nf = NumberFormat.getInstance();
	nf.setParseIntegerOnly(true);
	nf.setMaximumIntegerDigits(3);
	nf.setMinimumIntegerDigits(3);

	PrintStream pout = new PrintStream(System.err);
	PrintStream passout = null;
	try{
	    passout = new PrintStream(new FileOutputStream("password.crypto"));
	} catch (IOException e) {
	    System.err.println("Stuffed: password output "+e);
	    return;
	}

	PrintStream srcdump = null;
	try {
	    srcdump = new PrintStream(new FileOutputStream("src.txt"));
	} catch (IOException e) {
	    System.err.println("Stuffed: source dump "+e);
	    return;
	}
	
	// Make  plot of the sources as we generate them.

	//SphereFrame plot = new SphereFrame(" Sources: RA/Dec:", new SpherePlot(0.25f, 0.25f));
	//plot.setBounds(100,100,400,400);
	//plot.setVisible(true);
	
	Root             root = null;	  
	Tag              tag = null;
	User             user = null;
	Proposal         proposal = null;
	Group            group = null;
	Observation      obo = null;
	Source           source = null;
	TelescopeConfig  tc = null;
	InstrumentConfig ic = null;
	PipelineConfig   pc = null;
	Detector         detector = null;
	Mosaic           mosaic = null;
	
	String key = null;
	
	
	// Create a DB.
	try { 
	    System.err.println("Starting transaction");
	    Transaction trans = Transaction.current();
	    trans.abort();
	    Map rootMap = trans.parent().root();
	    System.err.println("Got rootMap");
	    //SortedMap rootEntry = new StorableSortedDictionary();
	    //rootMap.put("ROOT", rootEntry);
	    System.err.println("Placed root-entry in root-map");
	    
	    try {
		// Number of elements at each level.
		nn = Integer.parseInt(args[1]);
		System.err.println("Will be using: nn "+nn);
	    } catch (NumberFormatException nfe) {System.err.println("Elements: "+nfe);usage();return;}
	    User[] userlist = new User[2*nn*nn];
	    int usercount = 0;
	    Source[] sourceList = new Source[5*nn*nn];
	  
	    root = new Root("LT_Phase2_001");
	    root.setSchedCoeff(1.0f);
	    
	    // rootEntry.put(root.getName(), root);
	    rootMap.put(root.getName(), root);


	    System.err.println("Placed Root object in root-entry-map");
	    // Make some Tags.
	    
	    for (int i1 = 1; i1 <= nn; i1++) {
		
		tag = new Tag(tags[i1-1]); //use the real names
		
		tag.setSchedCoeff(1.0f);

		tag.setTargetFraction(BRIGHT, EXCELLENT, 0.15f);
		tag.setTargetFraction(BRIGHT, AVERAGE,   0.15f);
		tag.setTargetFraction(BRIGHT, POOR,      0.15f);
		tag.setTargetFraction(DARK,   EXCELLENT, 0.15f);
		tag.setTargetFraction(DARK,   AVERAGE,   0.3f);
		tag.setTargetFraction(DARK,   POOR,      0.1f);

		float tat = (float)Math.random()*500;
		tag.setTotalAllocatedTime(tat);
		float tut = 0.15f*tat;
		tag.setTotalAchievedTime(0.0f);

		//tag.setAchievedTime(BRIGHT, EXCELLENT, tag.getTargetFraction(BRIGHT, EXCELLENT)*tut);
		//tag.setAchievedTime(BRIGHT, AVERAGE,   tag.getTargetFraction(BRIGHT, AVERAGE)*tut);
		//tag.setAchievedTime(BRIGHT, POOR,      tag.getTargetFraction(BRIGHT, POOR)*tut);
		//tag.setAchievedTime(DARK,   EXCELLENT, tag.getTargetFraction(DARK,   EXCELLENT)*tut);
		//tag.setAchievedTime(DARK,   AVERAGE,   tag.getTargetFraction(DARK,   AVERAGE)*tut);
		//tag.setAchievedTime(DARK,   POOR,      tag.getTargetFraction(DARK,   POOR)*tut);

		tag.setAchievedTime(BRIGHT, EXCELLENT, 0.0f);
		tag.setAchievedTime(BRIGHT, AVERAGE,   0.0f);
		tag.setAchievedTime(BRIGHT, POOR,      0.0f);
		tag.setAchievedTime(DARK,   EXCELLENT, 0.0f);
		tag.setAchievedTime(DARK,   AVERAGE,   0.0f);
		tag.setAchievedTime(DARK,   POOR,      0.0f);
		System.err.println("new Tag ["+tag.getName()+"]");
		try {Thread.sleep(1000);} catch (InterruptedException ie) {}
		root.addTag(tag);

		
		// Make some Users.

		for (int i2 = 1; i2 <= 2*nn; i2++) {
		    if (i1 == 1 && i2 <= nn) {
			 user = new User(users[i2-1]);
		    } else {
			user = new User("U-"+i2);
		    }
		    user.setSchedCoeff(1.0f);
		    if (i1 == 1 && i2 <= nn) {
			user.setEmail(users[i2-1]+"@astro.livjm.ac.uk");
			user.setOrganization("ARI, Liverpool John Moores University");
		    } else {
			user.setEmail(user.getName()+"@"+tag.getName()+".ac.uk");
		    }
		    user.setPassword("xy"+user.getName()+"zzz");
		    System.err.println("new User ["+user.getName()+"]");
		    System.err.println("------[ "+user.getEmail()+" ]");
		    tag.addUser(user);
		    
		    // Make some Proposals.

		    for (int i3 = 1; i3 <= nn; i3++) {
			pcc++;
			String name = String.valueOf(tag.getName().charAt(0))+"L00B"+nf.format(pcc);
			
			proposal = new Proposal(name);
			proposal.setAllocatedTime(2.0f+(float)Math.random()*20.0f); // 2+r(20) hours
			proposal.setSchedCoeff(1.0f);
			proposal.setExported(false);
			
			float tf = 0.0f;
			
			proposal.setAllocatedFraction(DARK,   EXCELLENT, 0.1f);
			proposal.setTimeUsed         (DARK,   EXCELLENT, 0.0f);
			
			
			proposal.setAllocatedFraction(DARK,   AVERAGE,   0.1f);
			proposal.setTimeUsed         (DARK,   AVERAGE,   0.0f);
			
			
			proposal.setAllocatedFraction(DARK,   POOR,      0.1f);
			proposal.setTimeUsed         (DARK,   POOR,      0.0f);
			
			
			proposal.setAllocatedFraction(BRIGHT, EXCELLENT, 0.2f);
			proposal.setTimeUsed         (BRIGHT, EXCELLENT, 0.0f);
			
			proposal.setAllocatedFraction(BRIGHT, AVERAGE,   0.1f);
			proposal.setTimeUsed         (BRIGHT, AVERAGE,   0.0f);
			
			proposal.setAllocatedFraction(BRIGHT, POOR,      0.4f);
			proposal.setTimeUsed         (BRIGHT, POOR,      0.0f);
			
			proposal.setAllocatedFixedFraction(0.5);
			proposal.setUsedFixedTime(0L);

			int flags = 0;
			flags |= (Math.random()>0.5 ? 1:0);
			flags |= (Math.random()>0.5 ? 2:0);
			flags |= (Math.random()>0.5 ? 4:0);			
			flags |= (Math.random()>0.5 ? 8:0);
			if (flags == 0) flags = 1; // Just incase do a RAT config.
			/// #### TEMP RAT ONLY.........
			/// #### TEMP RAT ONLY.........
			//flags = RAT | SUPIR; 
			flags = 1;
			/// #### TEMP RAT ONLY.........
			/// #### TEMP RAT ONLY.........
			System.err.println("Flags: "+Integer.toBinaryString(flags));
			proposal.setInstrumentsAllowed(flags);
			
			proposal.setPustAbstract(new String(proposal.getName()+" // A very interesting thing to do. "));
			proposal.setScienceAbstract(new String(proposal.getName()+" // A very Scientific Proposal"));

			// All proposals are activated upto 30 days ago and will terminate in 6 months.
			long d1 = yearStart;
			proposal.setLastLocked(d1);	
			// about an hour later.		
			proposal.setLastUnLocked(d1 + 4000000L); 
			proposal.setLastEditor(new String("JMU ADMIN"));
			proposal.setLastRegId(REGCODE);
			// upto 30 days before start date.
			proposal.setActivationDate(d1 - 86400000L*((long)(Math.random()*30.0))); 
			// ~180 days from start.
			proposal.setExpiryDate(d1+(180*86400000L));
			proposal.setExported(false);
			System.err.println("new Proposal ["+proposal.getName()+"]");
		
			//###
			user.addProposal(proposal.getName());
			proposal.setPath(user.getFullPath());
			//###

			// Dump the password.
			String password = "xx"+name.toLowerCase()+"yy";
			// e.g. JL00B06 becomes xxjl00b06yy.
			
			passout.println(proposal.getFullPath()+"="+password);
			System.err.println("Proposal: "+proposal.getFullPath()+" PWD: "+password);

			try {Thread.sleep(500);} catch (InterruptedException ie) {}
			// Make some TelescopeConfigs.
			
			for (int i4 = 1; i4 <= nn; i4++) {
			    tc = new TelescopeConfig("TC#"+i4);
			    tc.setSetupTime((float)(Math.random()*20000.0f));
			    //tc.setFocusOffset((float)(Math.random()*4.0f));// microns
			    tc.setFocusOffset(0.0f);
			    tc.setAutoGuiderUsageMode(TelescopeConfig.AGMODE_NEVER);
	      			   
			    int ssm = (int)(Math.random()*3); // RANK. range, user/pixels.
			    //tc.setGuideProbePosition(Math.random()*4.0); // outside edge
			    tc.setGuideProbePosition(0.0);
			    tc.setRotatorAngleMode(Math.random() < 0.5 ? 0 : 1); // SKY/MOUNT
			    tc.setSkyAngle(Math.random()*0.2); // rads

//  			    tc.setAutoGuiderStarSelectionMode(ssm); // RANK. range, user/pixels.
//  			    tc.setAutoGuiderStarSelectionEnabled(Math.random() < 0.8);  // 80% are set
//  			    int ssp1 = 0;
//  			    int ssp2 = 0;
//  			    switch (ssm) {
//  			    case TelescopeConfig.STAR_SELECTION_RANK:
//  				tc.setAutoGuiderStarSelection1((int)(Math.random()*5)+1);
//  				break;
//  			    case TelescopeConfig.STAR_SELECTION_RANGE:
//  				ssp1 = (int)(Math.random()*8)+10;
//  				ssp2 = ssp1 + 5;
//  				tc.setAutoGuiderStarSelection1(ssp1);
//  				tc.setAutoGuiderStarSelection2(ssp2);
//  				break;
//  			    case TelescopeConfig.STAR_SELECTION_PIXEL:
//  				ssp1 = (int)(Math.random()*1024);
//  				ssp2 = (int)(Math.random()*1024);
//  				tc.setAutoGuiderStarSelection1(ssp1);// Pixel-X
//  				tc.setAutoGuiderStarSelection2(ssp2);// Pixel-Y
//  				break;
//  			    }
			    // #####NOTE WE HAVE FUDGED FOR ON_TEL TESTING####
			    tc.setAutoGuiderStarSelectionMode(TelescopeConfig.STAR_SELECTION_RANK);
			    tc.setAutoGuiderStarSelectionEnabled(true);
			    tc.setAutoGuiderStarSelection1((int)(Math.random()*3)+1);
			   
			    proposal.addTelescopeConfig(tc);
			    
			    //System.err.println("new TConfig ["+tc.getName()+"]");
			    
			}
			
			// Make some InstumentConfigs.
			// i4 = 0,,3 => inst = {CCD, SUPIR, MES, NUVIEW}
			Vector ics = new Vector();
			ics.clear();
			for (int i4 = 0; i4 <= 3; i4++) {
			    
			    
			    for (int i5 = 0; i5 < 8; i5++) {
				ic = null;
				if (i4 == 0 && ((flags & RAT) == RAT)) {
				    System.err.println("Make RAT#"+(8*i4+i5));
				    //ic = new CCDConfig("RAT#"+(8*i4+i5));
				    proposal.setXInstrumentsAllowed("RATCAM", true);
				    proposal.setXInstrumentsAllowed("CCD3CAM", true);
				    // ### TEMP FOR CCD3 TEsts
				    //if (Math.random() > 0.5)
				    ic = new dev.lt.RATCamConfig("RAT#"+(8*i4+i5));
				    //else
				    //ic = new dev.lt.CCD3CamConfig("CCD3#"+(8*i4+i5));

				    ((CCDConfig)ic).setSetupTime((float)(Math.random()*20000.0f));
				    ((CCDConfig)ic).setUpperFilterWheel(uppers[(int)(Math.random()*6)+1]);
				    ((CCDConfig)ic).setLowerFilterWheel(lowers[(int)(Math.random()*6)+1]);
				    ic.setCalibrateBefore(Math.random() > 0.5);
				    ic.setCalibrateAfter(Math.random() > 0.5);
				    detector = (CCDDetector) ic.getDetector(0);
			    
				    detector.clearAllWindows();			
				   
				    detector.setXBin(2);
				    detector.setYBin(2);
				}
				if (i4 == 1 && ((flags & SUPIR) == SUPIR)) {
				    System.err.println("Make SUPIR#"+(8*i4+i5));
				    proposal.setXInstrumentsAllowed("SUPIRCAM", true);
				    ic = new IRCamConfig("SUP#"+(8*i4+i5));
				    ((IRCamConfig)ic).setSetupTime((float)(Math.random()*20000.0f));
				    ((IRCamConfig)ic).setFilterWheel(uppers[(int)(Math.random()*6)+1]);
				    //((IRCamConfig)ic).setLowerFilterWheel(lowers[(int)(Math.random()*6)+1]);
				    ic.setCalibrateBefore(Math.random() > 0.5);
				    ic.setCalibrateAfter(Math.random() > 0.5);
				    detector = (IRCamDetector) ic.getDetector(0);
			    
				    detector.clearAllWindows();			
				   
				    detector.setXBin(2);
				    detector.setYBin(2);
				}
				
				if (i4 == 2 && ((flags & MES) == MES)) {  
				    System.err.println("Make MES#"+(8*i4+i5)); 
				    proposal.setXInstrumentsAllowed("MESSPEC", true);
				    ic = new HiResSpecConfig("MES#"+(8*i4+i5));
				    ((HiResSpecConfig)ic).setSetupTime((float)(Math.random()*20000.0f));
				    ((HiResSpecConfig)ic).setFilterSlideName("TEST");
				    ic.setCalibrateBefore(Math.random() > 0.5);
				    ic.setCalibrateAfter(Math.random() > 0.5);
				    detector = (HiResSpecDetector) ic.getDetector(0);
				    
				    detector.clearAllWindows();			
				  
				    detector.setXBin(2);
				    detector.setYBin(2);
				}
				
				if (i4 == 3 && ((flags & NUVIEW) == NUVIEW)) { 
				    System.err.println("Make NUV#"+(8*i4+i5));
				    proposal.setXInstrumentsAllowed("NUVSPEC", true);
				    ic = new LowResSpecConfig("NUV#"+(8*i4+i5));
				    ((LowResSpecConfig)ic).setSetupTime((float)(Math.random()*20000.0f));
				    ((LowResSpecConfig)ic).setWavelength(Math.random()*5000.0+4500.0);
				    ic.setCalibrateBefore(Math.random() > 0.5);
				    ic.setCalibrateAfter(Math.random() > 0.5);
				    detector = (LowResSpecDetector) ic.getDetector(0);
			    
				    detector.clearAllWindows();			
				   
				    detector.setXBin(2);
				    detector.setYBin(2);
				}
				if (ic != null) {
				    proposal.addInstrumentConfig(ic);
				    System.err.println("Added ic: "+ic.toString()+" to proposal");
				    ics.add(ic);
				    System.err.println("Added ic: "+ic.getName()+" to vector");
				}
			    }
			}
			
			System.err.println("Vector size: "+ics.size());
			
			// Make some PipeLineConfigs.
			
			for (int i4 = 1; i4 <= nn; i4++) {
			    pc = new PipelineConfig("PIPE#"+i4);			   			   
			    pc.setDebias(true);
			    pc.setFlatfield(true);
			    pc.setIdCosmic(false);
			    pc.setRemoveCosmic(true);
			    pc.setAstroCalib(true);
			    pc.setFrameZero(false);
			    pc.setPhotometry(true);
			    pc.setRelativePhotometry(false);
			    pc.setAstrometry(true); 
			    proposal.addPipelineConfig(pc);
			    //System.err.println("new PipeConfig ["+pc.getName()+"]");
			    
			}
			
			
			// Make some Groups.
			
			for (int i4 = 1; i4 <= 40; i4++) {
			    countGroup++;
			    long pad   = proposal.getActivationDate();
			    long etime = pad + (long)(Math.random()*(double)msecYear*2);
			    total++;
			    long ftime = 0L;
			    if (total%20 == 1) {
				// Occasionally make a FixedGroup. (1 IN 20).
				fixed++;
				// about every 1 hours for now from starttime.
				ftime = start.getTime() + fixed*3600*1000L;
				Date date = new Date(ftime);
				group = new FixedGroup("FG#"+i4+"("+mdf.format(date)+")");
				// Set a fixedtime  during Y2K.
				((FixedGroup)group).setFixedTime(ftime);				
				System.err.println("Fixed time: " + date.toGMTString());			  
			    } else if
				(total%5 == 1) {
				// About 1 in 5 are Monitors.
				group = new MonitorGroup("MG#"+i4);
				ftime = yearStart + (long)(Math.random()*(double)msecYear);
				((MonitorGroup)group).setStartDate(ftime);
				((MonitorGroup)group).setEndDate(ftime+2*msecYear);
				// period at least 4 hours upto 2 weeks
				long pp = 4*3600*1000L+(long)(Math.random()*14*86400*1000);
				((MonitorGroup)group).setPeriod(pp);
				// float 20% upto 80%
				((MonitorGroup)group).setFloatFraction(0.2f + (float)(Math.random()*0.4f));	
				System.err.println("Monitor Period: "+(pp/1000.0)+"secs");
			    } else {
				// Mostly make normal Groups.
				group = new Group("G#"+i4);	
				// 1 in 10 Normals are already done.
				if (Math.random() > 0.9) {
				    group.setDone(true);
				    long dd =  etime - pad;
				    group.setDoneDate(pad+(dd/2)); // done half way to expiry
				} else {
				    group.setDone(false);
				}	
				group.setDone(false);
			    }			   			   	    

	//  		    if (Math.random() > 0.7)
//  				group.setMinimumLunar(Group.DARK);			             
//  			    else 
//  				group.setMinimumLunar(Group.BRIGHT);

//  			    if (Math.random() > 0.9)
//  				group.setMinimumSeeing(Group.EXCELLENT);
//  			    else if
//  				(Math.random() > 0.6)
//  				group.setMinimumSeeing(Group.AVERAGE);
//  			    else
//  				group.setMinimumSeeing(Group.POOR);
			    
			    group.setMinimumLunar(Group.BRIGHT);
			    group.setMinimumSeeing(Group.POOR);

			    System.err.println("Group:LS ["+group.getMinimumLunar()+":"+group.getMinimumSeeing()+"]");

			    group.setSchedCoeff(1.0f);
			    //System.err.println("new "+group.getClass().getName()+" ["+group.getName()+"]");
			    group.setExpiryDate(etime);
			    proposal.addGroup(group);
			    
			    // Make some Source objects for this Group.
			    
			    // The center point of source Group.
			   
			    double dec = 0.0;
			    double ra  = 0.0;
			    double tt  = 0.0;

			   

			    //plot.putPoint((float)Math.toDegrees(ra), 
				//	  (float)Math.toDegrees(dec), 0);	    
			    int sourceCount = 0; 
			    for (int i5 = 1; i5 <= 3*nn; i5++) {				
				switch (i5) {
				case 1:
				    source = new Comet("Comet#"+i4); 				   
				    ((Comet)source).setElementEpoch(50000.0 + Math.random()*100.0);
				    ((Comet)source).setArgPeri(Math.random()*6.283);
				    ((Comet)source).setPeriDist(Math.random()*20.0);
				    ((Comet)source).setLongAscNode(Math.random()*6.283);
				    ((Comet)source).setOrbitalInc(Math.random()*0.57);
				    ((Comet)source).setEccentricity(Math.random());
				    sourceList[sourceCount] = source;
				    break;
				case 2:
				    source = new MinorPlanet("MinorPlanet#"+i4); 				
				    ((MinorPlanet)source).setElementEpoch(50000.0 + Math.random()*100.0);
				    ((MinorPlanet)source).setArgPeri(Math.random()*6.283);
				    ((MinorPlanet)source).setLongAscNode(Math.random()*6.283);
				    ((MinorPlanet)source).setOrbitalInc(Math.random()*0.157);
				    ((MinorPlanet)source).setEccentricity(Math.random());
				    ((MinorPlanet)source).setMeanDistance(Math.random()*30.0);
				    ((MinorPlanet)source).setMeanAnomaly(Math.random()*6.283);
				    
				    sourceList[sourceCount] = source;
				    break;
				case 3:
				    source = new MajorPlanet("MajorPlanet#"+i4);  				 
				    ((MajorPlanet)source).setElementEpoch(50000.0 + Math.random()*100.0);
				    ((MajorPlanet)source).setLongPeri(Math.random()*6.283);
				    ((MajorPlanet)source).setLongAscNode(Math.random()*6.283);
				    ((MajorPlanet)source).setOrbitalInc(Math.random()*0.157);
				    ((MajorPlanet)source).setDailyMotion(6.283/(Math.random()*7000.0));
				    ((MajorPlanet)source).setEccentricity(Math.random()*0.2);
				    ((MajorPlanet)source).setMeanDistance(Math.random()*30.0);
				    ((MajorPlanet)source).setMeanLongitude(Math.random()*6.283);  		    	  
				    sourceList[sourceCount] = source;
				    break;
				case 4:
				    source = new CatalogSource("The Moon#"+i4, CatalogSource.MOON);
				    sourceList[sourceCount] = source;
				    break;
				default:
				    // Name the Source relative to this Group.
				    source = new ExtraSolarSource("ExSrc#"+((i4-1)*(nn-3)+i5-3)); 
//  				    // RA  (0..360)
//  				    // Dec (-90 .. +90)
//  				    // Chose stars which are around the centre for this Group.
//  				    // Add upto 20 degs to RA.
//  				    ra  += Math.toRadians(Math.random()*20.0);
//  				    if (ra > 2.0*Math.PI)
//  					ra -= 2.0*Math.PI;
//  				    // Add upto 20 degs to dec.
//  				    dec += Math.toRadians(Math.random()*20.0);
//  				    // If dec over 90 then make 80 to 90
//  				    if (dec > Math.PI/2.0) 
//  					dec = Math.PI/2.0 - Math.toRadians(Math.random()*10.0);
//  				    // If dec < -90 then make -80 to -90
//  				    if (dec < -Math.PI/2.0)
//  					dec = -Math.PI/2.0 + Math.toRadians(Math.random()*10.0);


				    // We select stars which are above -10 degrees dec and
				    // distributed evenly across the sky...
//  				    do {
//  					do {
//  					    dec = Math.random()*Math.PI/2.0;       		      
//  					    tt  = Math.random();            
//  					} while (Math.cos(dec) < tt);
					
//  					// Do southern sky.
//  					if (Math.random() >= 0.5)
//  					    dec = -dec;
//  				    } while (dec < Math.toRadians(-10)); 
				    
 				    ra  = Math.random()*2.0*Math.PI;

				    // Pick a random distributed via cos().
				    // ALG-C
				    double dd = 0.0;
				    do {
					tt = Math.random();
					dd = Math.asin(tt);
					if (Math.random() >= 0.5)
					    dd = -dd;
				    } while (dd < Math.toRadians(-10.0)); 

				    dec = dd;

				    ((ExtraSolarSource)source).setRA(ra);
				    ((ExtraSolarSource)source).setDec(dec);
				    ((ExtraSolarSource)source).setPmRA(Math.random()*3.0);
				    ((ExtraSolarSource)source).setPmDec(Math.random()*3.0);			     
				    ((ExtraSolarSource)source).setParallax(0.0);
				    ((ExtraSolarSource)source).setRadialVelocity(Math.random()*22.2-11.1);
				    sourceList[sourceCount] = source;
				    //Position posn = source.getPosition();
				   
				   
				    //System.err.println("new Source ["+source.getName()+
				    //     "] at RA: "+ posn.getRA()+
				    //   " Dec: "+posn.getDec()+
				    //   " made using dec: "+dec);
				    break;
				}
				
				source.setEpoch(2000.0f);
				source.setEquinox(2000.0f);
				source.setEquinoxLetter('J');
				source.setFrame(Source.FK5);
				
				sourceCount++; 
				proposal.addSource(source);
				
				//System.err.println("New Source: ["+source.getClass().getName()+
				//   "]: "+source.getPath()+"//"+source.getName());
				
				
				//plot.putPoint(posn.getRA(),posn.getDec());
			    }
			    
			    // Make some Observations.

			    //int nobs = (int)(Math.random()*4.0 + 1.0);
			    int nobs = 1;

			    for (int i5 = 1; i5 <= nobs; i5++) { 
			   
				countObs++;
				obo = new Observation("OBS#"+i5);
				obo.setSchedCoeff(1.0f);
				obo.setExposeTime((float)(Math.random()*120000.0f + 180000.0f));
				obo.setNumRuns((int)(Math.random()*3)+1);
				if (Math.random() > 0.8) {
				    obo.setConditionalExposure(true);
				}
				
			
				mosaic = new Mosaic();

//  				if (Math.random() > 0.99) {
//  				    mosaic.setPattern(Mosaic.ARRAY);
//  				    mosaic.setOffsetRA(Math.random()*0.03);
//  				    mosaic.setOffsetDec(Math.random()*0.03);
//  				    mosaic.setCellsRA(3);
//  				    mosaic.setCellsDec(3);
//  				} else if (Math.random() > 0.66) {
//  				    mosaic.setPattern(Mosaic.CROSS);
//  				    mosaic.setOffsetRA(Math.random()*0.03);
//  				    mosaic.setOffsetDec(Math.random()*0.03);
//  				    mosaic.setCellsRA(3);
//  				    mosaic.setCellsDec(1);
//  				} else {
//  				    mosaic.setPattern(Mosaic.SINGLE);
//  				}

				// ##### TEMP FOR ON-TEL TESTS####
				mosaic.setPattern(Mosaic.SINGLE);
				obo.setMosaic(mosaic);
			       				
				group.addObservation(obo);
				
				//System.err.println("For Group: "+group.getPath()+"/"+group.getName());
				//System.err.println("new Observation ["+obo.getPath()+"/"+obo.getName()+"]");
				//System.err.println("....exposure: "+(obo.getExposeTime()/60000.0f)+" mins");
				key = "TC#"+String.valueOf((int)(Math.random()*nn+1));
				//System.err.println(" Tc path is: "+key);
				obo.setTelescopeConfig(proposal.findTelescopeConfig(key));
				//System.err.println("..adding TConfig");
				
				int ll = ics.size();
				int kk = (int)(Math.random()*(ll-2))+1;
				System.err.println("Choosing IC: Vec-Size = "+ll+
						   " kk: "+kk);
				InstrumentConfig mic = (InstrumentConfig) ics.elementAt(kk);			      
				obo.setInstrumentConfig(mic);
				System.err.println("Obs."+obo.getFullPath()+"..adding IConfig "+mic.getName());
								
				key = "PIPE#"+String.valueOf((int)(Math.random()*nn+1));
				//System.err.println(" Pipe path is: "+key);
				obo.setPipelineConfig(proposal.findPipelineConfig(key));
				//System.err.println("..adding PipeConfig");
									   
				//System.err.println("..adding Source");
				Source src = sourceList[(int)(Math.random()*sourceCount)];
				obo.setSource(src);
				
				srcdump.println(obo.getFullPath()+"\t Src: "+src.toString());
				
				//try {Thread.sleep(500);} catch (InterruptedException ie) {}
				
			    } // obs
			    
			    // Do this now - only done once or at any further updates.
			    Scheduling.calculateExecutionTimes(group);
			    
			} // group
			
			// Save the proposal now.
			try {
			    File file = new File("store/"+proposal.getName());			
			    ObjectOutputStream fout = new ObjectOutputStream(new FileOutputStream(file));
			    fout.flush();
			    fout.writeObject(proposal);
			    fout.flush();
			    System.err.println("Saved Proposal to: "+file.getPath());
			} catch (IOException e) {
			    System.err.println("Error flushing Proposal: "+proposal.getFullPath()); 
			    e.printStackTrace();
			}
			
			// Print out its XInst stuff.
			Iterator insts = proposal.listXInstrumentsAllowed();
			while (insts.hasNext()) {
			    String ia = (String)insts.next();
			    System.err.println("Allow:["+ia+"]");
			}

		    } // proposal
			
		    trans.commit();
		    rootMap   = trans.parent().root();
		    //rootEntry = (SortedMap)rootMap.get("ROOT");
		
		    //root      = (Root)rootEntry.get("LT_Phase2_001");
		    root      = (Root)rootMap.get("LT_Phase2_001");
		    System.err.println("******Re-established Root location after committing user - "+user.getName());
		
		} // user
		
		
	    } // tag
		
	    // Make some CoI links, 2 per Proposal, from any Tag.
	    usercount = 0;
	    System.err.println("Starting COI linking:");
	    Iterator it1 = root.listAllTags();
	    while (it1.hasNext()) {
		tag = (Tag)it1.next();
		Iterator it2a = tag.listAllUsers();
		while (it2a.hasNext()) {
		    user = (User)it2a.next();
		    userlist[usercount] = user; 
		    usercount++;
		}
		Iterator it2b = tag.listAllUsers();
		while (it2b.hasNext()) {
		    user = (User)it2b.next();
		    Iterator it3 = user.listAllProposals();
		    while (it3.hasNext()) {
			KVPair pair = (KVPair)it3.next();
			String npname = (String)pair.getKey();
			try {
			    File file = new File("store/"+npname);
			    ObjectInputStream fin = new ObjectInputStream(new FileInputStream(file));	       	    
			    proposal = (Proposal)fin.readObject();
			    System.err.println("Read prop back from: "+file.getPath());
			} catch (Exception e) {
			    System.err.println("Error reading in Proposal: "+npname);
			    e.printStackTrace();
			}
			for (int i4 = 0; i4 < 1; i4++) {
			    User couser = userlist[(int)(Math.random()*usercount)];			   
			    String coname = couser.getPath()+"/"+couser.getName();
			    String pname = proposal.getFullPath();
				// Dont let a user be CoI for his own (PI) proposal.
			    if (!pname.equals(coname)) { 			   
				couser.addCoIProposal(pname);
				System.err.println("Adding CoI: "+coname+
						   " to Proposal: "+pname);
			    }
			}
		    }
		}
	    }
	    
	    System.err.println("Made total of "+fixed+" FixedGroups from "+
			       countGroup+" Groups with "+countObs+" Obs."); 
	    
	    trans.commit(); 
	    passout.close();
	} catch (Exception de) {
	    System.err.println("Some sort of big error: "+de);
	    de.printStackTrace();
	    return;
	} finally { 
	    System.err.println("OK DONE");
	    System.err.println("Closing DB");
	    DBRuntime.shutDown(true);	  
	}
    } // MAIN.

    private static void usage() {
	System.err.println("Usage:\n\tjava MakeDB <start-date> <elements>"+
			   "\n\twhere <start-date> is dd/MM/yyyy format");
    }

}  // end class def [MakeDB].


/** $Log: MakeDB.java,v $
/** Revision 1.1  2006/11/27 08:45:00  snf
/** Initial revision
/**
/** Revision 1.1  2006/11/27 08:37:05  snf
/** Initial revision
/** */
